﻿namespace Rosieks.Web.Flow
{
    using System;
    using System.Web.Mvc;

    public class WebflowManager : Rosieks.Web.Flow.IWebflowManager
    {
        private readonly IWebflowCatalog webflowCatalog;

        public WebflowManager()
            : this(null)
        {
        }

        public WebflowManager(IWebflowCatalog catalog)
        {
            this.webflowCatalog = catalog ?? HashtableWebflowCatalog.Instance;
        }

        public WebflowContext Load(ControllerContext context)
        {
            return this.Load(context, null);
        }

        public WebflowContext Load(ControllerContext context, string name)
        {
            string webflowName = name ?? this.GetWebflowName(context.RouteData);

            if (string.IsNullOrWhiteSpace(webflowName))
            {
                // TODO: Move string to resources.
                throw new InvalidOperationException("The name of Webflow must be assigned");
            }

            var webflowModel = this.webflowCatalog.Load(webflowName);
            var webflowContext = WebflowContextProviders.Providers.GetContext(webflowModel, context, webflowName);
            if (webflowContext != null)
            {
                webflowContext.Webflow = webflowModel;
                webflowContext.OnLoad();
            }
            else
            {
                webflowContext = new WebflowContext();
                webflowContext.Webflow = webflowModel;
                webflowContext.OnStart();
            }

            WebflowContext.SetCurrent(context.HttpContext, webflowContext);

            return webflowContext;
        }

        public void Save(ControllerContext context)
        {
            var webflowContext = WebflowContext.GetCurrent(context.HttpContext);

            if (webflowContext.CurrentState == null || (webflowContext.CurrentState.IsEndState && webflowContext.CurrentState == webflowContext.CurrentElement))
            {
                webflowContext.OnFinish();

                WebflowContextProviders.Providers.DeleteContext(webflowContext.Webflow, context, webflowContext);
            }
            else
            {
                WebflowContextProviders.Providers.SetContext(webflowContext.Webflow, context, webflowContext);
            }
        }

        private string GetWebflowName(System.Web.Routing.RouteData routeData)
        {
            object webflowNameFromRoute;
            routeData.Values.TryGetValue(RouteData.WebflowParamName, out webflowNameFromRoute);

            return webflowNameFromRoute as string;
        }
    }
}
